#include "StdAfx.h"
#include "StarCraftIdentifyHistories.h"

//////////////////////////////////////////////////////////////////////////
//Author	:	Ross Conroy ross.conroy@tees.ac.uk
//Date		:	29/10/2014
//
//This class is specific to the star craft domain because it first filters
//the data by unit ID and treads each unit ID as its own file
//////////////////////////////////////////////////////////////////////////

StarCraftIdentifyHistories::StarCraftIdentifyHistories(void)
{
}

//////////////////////////////////////////////////////////////////////////
//gets the index of the unit id
//////////////////////////////////////////////////////////////////////////
int StarCraftIdentifyHistories::GetColIndex(string header, string unitIDCol)
{
	int unitIdIndex = 0;

	int i = 0;
	while (header.find(",", 0) != string::npos)
	{
		size_t  pos = header.find(",", 0);
		string temp = header.substr(0, pos);
		header.erase(0, pos + 1);
		if(temp == unitIDCol)
		{
			unitIdIndex = i;
		}

		i++;
	}

	return unitIdIndex;
}

//////////////////////////////////////////////////////////////////////////
//gets the unit ID based on the index
//////////////////////////////////////////////////////////////////////////
int StarCraftIdentifyHistories::GetColIntData(string original, int colIndex)
{
	int unitID = 0;

	int i = 0;
	while (original.find(",", 0) != string::npos)
	{
		size_t  pos = original.find(",", 0);
		string temp = original.substr(0, pos);
		original.erase(0, pos + 1);
		if(i == colIndex)
		{
			unitID = atoi(temp.c_str());
			return unitID;
		}
		i++;
	}

	return unitID;
}

//////////////////////////////////////////////////////////////////////////
//compresses the time steps of a list of data rows
//////////////////////////////////////////////////////////////////////////
list<DataRow> StarCraftIdentifyHistories::CompressTimeSteps(list<DataRow> inputRows, int timeStepDuration)
{
	list<DataRow> compressed;

	bool seenEnemy = false;
	bool attacked = false;
	bool underAttack = false;
	int lastTime = inputRows.front().time;

	for(list<DataRow>::iterator it = inputRows.begin(); it != inputRows.end(); it++)
	{
		DataRow tempRow = *it;
		/*
		if(!lastTime)
		{
		lastTime == tempRow.time;
		}*/

		if((tempRow.time - lastTime) >= timeStepDuration)
		{
			DataRow row;
			if(attacked)
			{
				row.action = "Attack";
			}
			else
			{
				row.action = "Escape";
			}

			if(seenEnemy)
			{
				row.observation = "See";
			}
			else
			{
				row.observation = "DontSee";
			}

			if(underAttack)
			{
				row.state = "UnderAttack";
			}
			else
			{
				row.state = "NotUnderAttack";
			}

			row.time = lastTime;
			row.originalRow = tempRow.originalRow;

			compressed.push_back(row);

			seenEnemy = false;
			attacked = false;
			underAttack = false;
			lastTime = tempRow.time;
		}

		if(tempRow.action == "1" || tempRow.action == "Attack")
		{
			attacked = true;
		}

		if(tempRow.observation == "1" || tempRow.observation == "See")
		{
			seenEnemy = true;
		}

		if(tempRow.state == "1" || tempRow.state == "UnderAttack")
		{
			underAttack = true;
		}
	}
	
	return compressed;
}

//////////////////////////////////////////////////////////////////////////
//Separates rows based on unit id into a hash table where the unit id is
//the key and a list of strings for the rows as the value
//////////////////////////////////////////////////////////////////////////
hash_map<int, list<DataRow>> StarCraftIdentifyHistories::SeparateRowsByUnitID(string inputFile, string stateCol, string obsCol, string actionCol, string unitIDCol, string timeCol)
{
	DataRowFile dataRowFile;
	list<DataRow> dRows = dataRowFile.FileToRows(inputFile, stateCol, obsCol, actionCol);

	ifstream infile(inputFile.c_str());
	string headers;
	getline(infile, headers);
	infile.close();
	int unitIdIndex = GetColIndex(headers, unitIDCol);
	int timeIndex = GetColIndex(headers, timeCol);

	hash_map<int, list<DataRow>> separated;

	for(list<DataRow>::iterator it = dRows.begin(); it != dRows.end(); it++)
	{
		DataRow dRow = *it;
		int unitID = GetColIntData(dRow.originalRow, unitIdIndex);
		dRow.time = GetColIntData(dRow.originalRow, timeIndex);

		separated[unitID].push_back(dRow);		
	}

	return separated;
}

//////////////////////////////////////////////////////////////////////////
//fist separates by unit id then processes each id determining the history
//for each unit
//////////////////////////////////////////////////////////////////////////
void StarCraftIdentifyHistories::Identify(string inputFile, string outputFile, string stateCol, string obsCol, string actionCol, string unitIDCol, string timeCol, int maxHistory)
{
	ifstream infile(inputFile.c_str());
	string headers;
	getline(infile, headers);
	infile.close();

	hash_map<int, list<DataRow>> separated = SeparateRowsByUnitID(inputFile, stateCol, obsCol, actionCol, unitIDCol, timeCol);

	list<DataRow> rows;

	for(hash_map<int, list<DataRow>>::iterator it = separated.begin(); it != separated.end(); it++)
	{
		IdentifyHistories identify;

		list<DataRow> tempRows = it->second;

		//loop through rows and set actions and observations
		/*for(list<DataRow>::iterator itt = tempRows.begin(); itt != tempRows.end(); itt++)
		{
		DataRow tempRow = *itt;
		if(tempRow.action == "1")
		{
		tempRow.action = "Attack";
		}
		else
		{
		tempRow.action = "Escape";
		}

		if(tempRow.observation == "1")
		{
		tempRow.observation = "See";
		}
		else
		{
		tempRow.observation = "DontSee";
		}
		}*/

		tempRows = CompressTimeSteps(tempRows, 1000);
		tempRows = identify.Identify(tempRows, maxHistory);		

		for (list<DataRow>::iterator itr = tempRows.begin(); itr != tempRows.end(); itr++)
		{
			DataRow tempRow = *itr;
			rows.push_back(tempRow);
		}
	}

	DataRowFile dataRowFile;
	dataRowFile.OriginalRowsToFile(outputFile, rows, headers);
}